#include <stdlib.h>
#include <list>
#include <iostream>

#include <cubefs/core/types.hpp>
#include <cubefs/core/tools/types/relation.hpp>
#include <cubefs/core/tools/types/list_printer.hpp>

#include <typeinfo>

using namespace std;
using namespace cubefs;
using namespace cubefs::tools;


typedef enum {C0, C1, C2} Columns;

class V0 {};
class V1 {};
class V2 {};
class V3 {};
class V4 {};

template <typename ListItem>
struct SimpleValueProvider {
    static const BigInt Value = ListItem::Value;
};

template <typename T1_, Int V1_, typename T2_>
struct Record {
    typedef T1_ T1;
    typedef T2_ T2;
    static const Int V1 = V1_;
};

template <Int Name, typename ColumnType, typename Record> struct ValueProvider;

template <typename ColumnType, typename Record>
struct ValueProvider<C0, ColumnType, Record>:
    public TypeValue<ColumnType, typename Record::T1> {};

template <typename ColumnType, typename Record>
struct ValueProvider<C1, ColumnType, Record>:
    public StaticValue<ColumnType, Record::V1> {};


template <typename ColumnType, typename Record>
struct ValueProvider<C2, ColumnType, Record>:
    public TypeValue<ColumnType, typename Record::T2> {};


int main(int argc, char** argv) {
    
    typedef RelationMetadata<
                TypeListTool<Column<C0>, Column<C1, Int>, Column<C2> >::List,
                ValueProvider
    >                                                                           RM;


    typedef TypeListTool<
            Record<V2, 1, V4>,
            Record<V1, 23, V0>,
            Record<V4, -7, V2>,
            Record<V0, -5, V4>
    >::List                                                                     RelationList;


    typedef Projection<
                RM,
                TypeListTool<TypeCode<C0>, TypeCode<C1> >::List,
                RelationList
            >::List                                                             List;


//    typedef typename CreateColumnValuesList<Metadata, , RelationList::Head>::List List

    TypePrinterTool<AsListTool<List>::List>::Dump();


    return (EXIT_SUCCESS);
}

